home *** CD-ROM | disk | FTP | other *** search
/ HyperLib 1997 Winter - Disc 1 / HYPERLIB-1997-Winter-CD1.ISO.7z / HYPERLIB-1997-Winter-CD1.ISO / オンラインウェア / PRG / WASTE Object Handlers 1.2.2.sit / WASTE Object Handlers 1.2.2 / Other Source / GetFileIcon.c next >
Text File  |  1996-07-16  |  16KB  |  574 lines

  1. // File Object Handler Utilities for the WASTE Text Engine
  2. // Part of the WASTE Object Handler Library by Michael Kamprath, kamprath@kagi.com
  3. // maintenance by John C. Daub, hsoi@eden.com
  4. //
  5. // v1.2 28 March 1996,  Cleaned up the file with precompiler directives, removing potential
  6. //                        warning messages, updated PB calls to new function names
  7. //
  8. // v1.2.1 4 April 1996. Fixed a bad bug where PBHGetVolParmsAsync() was getting called when
  9. //                        PBHGetVolParmsSync() should have been called instead.
  10.  
  11.  
  12. #ifndef __ICONS__
  13. #include <Icons.h>
  14. #endif
  15. #ifndef __FINDER__
  16. #include <Finder.h>
  17. #endif
  18. #ifndef __FOLDERS__
  19. #include <Folders.h>
  20. #endif
  21. #include "GetFileIcon.h"
  22.  
  23. typedef struct getIconData { OSType        fileCreator;
  24.                              OSType        fileType;
  25.                              short        DTRefNum;
  26.                             } GetIconData;
  27.  
  28. extern Boolean IsVolEjected( short vRefNum );
  29. extern OSErr GetCustomFileIcon(FSSpec *filespec, IconSelectorValue iconSelector, Handle *theSuite);
  30. extern OSErr GetNormalFileIcon(CInfoPBRec *cpb, IconSelectorValue iconSelector, Handle *theSuite);
  31. extern void GetFinderFilename(StringPtr _finderFilename);
  32. extern pascal OSErr GetIconProc(ResType theType, Handle *theIcon, void *yourDataPtr);
  33. extern short FindDesktopDatabase(short firstVRefNum, OSType fileCreator); // returns a DT refnum or 0
  34. extern Boolean InOneDesktop(short vRefNum, OSType fileCreator, short *dtRefNum);
  35. extern pascal OSErr GetResourceIcons(Handle *theSuite, short theID, long theSelector);
  36. extern OSErr CopyEachIcon(Handle theSuite);
  37. extern pascal OSErr CopyOneIcon(ResType theType, Handle *theIcon, void *yourDataPtr);
  38. extern short FindGenericIconID(OSType theType, Boolean *inFinder);
  39. extern pascal OSErr Get1IconSuite(Handle *theSuite, short theID, long theSelector);
  40. extern pascal OSErr Get1Icon(ResType theType, Handle *theIcon, short *resID);
  41. extern pascal OSErr TestHandle(ResType theType, Handle *theIcon, void *yourDataPtr);
  42.  
  43.  
  44. /*    Custom icons numbered -16496 appear in aliases to volumes and
  45.     servers.  I don't know where this is documented.    */
  46. #define    kVolumeAliasIconResource    -16496
  47.  
  48.  
  49. /*    ------------------------------------------------------------------
  50.     GetFileIcon        Given a file specification for a file, folder, or
  51.                     volume, create an appropriate icon suite
  52.                     and find its label color.
  53.     ------------------------------------------------------------------ */
  54. pascal OSErr GetFileIcon(
  55. /* --> */    FSSpec                *thing,
  56. /* --> */    IconSelectorValue    iconSelector,
  57. /* <-- */    Handle                *theSuite)
  58. {
  59.     CInfoPBRec        cpb;
  60.     OSErr            err;
  61.  
  62.  
  63.     *theSuite = NULL;
  64.  
  65.     if( IsVolEjected(thing->vRefNum) )
  66.     {
  67.         err = volOffLinErr;
  68.     }
  69.     else
  70.     {
  71.         cpb.hFileInfo.ioVRefNum        = thing->vRefNum;
  72.         cpb.hFileInfo.ioDirID        = thing->parID;
  73.         cpb.hFileInfo.ioNamePtr        = thing->name;
  74.         cpb.hFileInfo.ioFDirIndex    = 0;
  75.         err = PBGetCatInfoSync( &cpb );
  76.  
  77.         if( !err )
  78.         {
  79.             if( (cpb.hFileInfo.ioFlAttrib & ioDirMask) == 0)    // file
  80.             {
  81.                 if(cpb.hFileInfo.ioFlFndrInfo.fdFlags & kHasCustomIcon)
  82.                 {
  83.                     err = GetCustomFileIcon(thing, iconSelector, theSuite );
  84.                 }
  85.                 else    // no custom icon
  86.                 {
  87.                     err = GetNormalFileIcon(&cpb, iconSelector, theSuite);
  88.                 }
  89.             }
  90.             // ----------- end of normal case --------------
  91.         }    
  92.     }
  93.  
  94.     // ------- error handler ---------
  95.     /*if(thing->parID == fsRtParID)    // a volume
  96.     {
  97.         if(err == volOffLinErr)
  98.         {
  99.             *labelColor = ttOffline;
  100.         }
  101.         err = GetVolumeIcon(thing->vRefNum, iconSelector, theSuite);
  102.     }*/
  103.  
  104.     return( err );
  105. }
  106.  
  107.  
  108. static Boolean    IsVolEjected( short vRefNum )
  109. {
  110.     OSErr            err;
  111.     HVolumeParam    vol_pb;
  112.     
  113.     vol_pb.ioNamePtr    = NULL;
  114.     vol_pb.ioVRefNum    = vRefNum;
  115.     vol_pb.ioVolIndex    = 0;
  116.     err = PBHGetVInfoSync( (HParmBlkPtr )&vol_pb );
  117.     
  118.     return( (err == noErr) && (vol_pb.ioVDRefNum > 0) );
  119. }
  120.  
  121.  
  122.  
  123. static OSErr    GetCustomFileIcon(
  124. /* --> */    FSSpec                *filespec,
  125. /* --> */    IconSelectorValue    iconSelector,
  126. /* <-- */    Handle                *theSuite)
  127. {
  128.     short    saveResFile, customResFile;
  129.     OSErr    err;
  130.     
  131.     saveResFile = CurResFile();
  132.     SetResLoad( false );
  133.     customResFile = FSpOpenResFile(filespec, fsRdPerm);
  134.  
  135.     SetResLoad( true );
  136.  
  137.     if(customResFile == -1)
  138.     {
  139.         err = ResError();
  140.     }
  141.     else
  142.     {
  143.         err = GetResourceIcons(theSuite, kCustomIconResource, iconSelector);
  144.         if( !err )
  145.         {
  146.             if( IsSuiteEmpty( *theSuite ) )
  147.             {
  148.                 err = GetResourceIcons(theSuite, kVolumeAliasIconResource, iconSelector);
  149.             }
  150.         }
  151.  
  152.         CloseResFile( customResFile );
  153.         UseResFile( saveResFile );
  154.     }
  155.     return( err );
  156. }
  157.  
  158.  
  159. static OSErr    GetNormalFileIcon(
  160. /* --> */    CInfoPBRec            *cpb,
  161. /* --> */    IconSelectorValue    iconSelector,
  162. /* <-- */    Handle                *theSuite)
  163. {
  164.     OSErr            err;
  165. //    long            dataSize;
  166. //    Handle            iconData;
  167. //    Byte            iconType;
  168.     GetIconData        getData;
  169.     short            iconID;
  170.     Boolean            inFinder;
  171.     short            saveResFile, FinderResFile, sysVRefNum;
  172.     long            sysDirID;
  173.     Str255            finderName;
  174.     IconActionUPP    getIconProcPtr;
  175.  
  176.  
  177.     iconID = FindGenericIconID(cpb->hFileInfo.ioFlFndrInfo.fdType, &inFinder );
  178.     saveResFile = CurResFile();
  179.  
  180.     if( inFinder )
  181.     {
  182.         FindFolder(kOnSystemDisk, kSystemFolderType, kDontCreateFolder, &sysVRefNum, &sysDirID);
  183.  
  184.         SetResLoad( false );
  185.         GetFinderFilename( finderName );
  186.         FinderResFile = HOpenResFile(sysVRefNum, sysDirID, finderName, fsRdPerm);
  187.         SetResLoad( true );
  188.  
  189.         if(FinderResFile == -1)
  190.         {
  191.             err = ResError();
  192.         }
  193.         else
  194.         {
  195.             err = GetResourceIcons(theSuite, iconID, iconSelector);
  196.             CloseResFile( FinderResFile );
  197.         }
  198.     }
  199.     else    // icons in desktop DB or in System
  200.     {
  201.         getData.DTRefNum = FindDesktopDatabase(cpb->dirInfo.ioVRefNum,
  202.             cpb->hFileInfo.ioFlFndrInfo.fdCreator );
  203.  
  204.         if(getData.DTRefNum != 0)    // the right icons are in some desktop
  205.         {
  206.             err = NewIconSuite( theSuite );
  207.             if( !err )
  208.             {
  209.                 getData.fileCreator    = cpb->hFileInfo.ioFlFndrInfo.fdCreator;
  210.                 getData.fileType    = cpb->hFileInfo.ioFlFndrInfo.fdType;
  211.                 if(getData.fileType == kApplicationAliasType)
  212.                 {
  213.                     getData.fileType = 'APPL';
  214.                 }
  215.                 getIconProcPtr = NewIconActionProc( GetIconProc );
  216.                 err = ForEachIconDo(*theSuite, iconSelector, getIconProcPtr, &getData);
  217.                 DisposeRoutineDescriptor( getIconProcPtr );
  218.             }
  219.         }
  220.         if( (getData.DTRefNum == 0) || IsSuiteEmpty( *theSuite ) )
  221.         {
  222.             UseResFile( 0 );
  223.             err = GetResourceIcons(theSuite, iconID, iconSelector);
  224.         }
  225.     }
  226.  
  227.     UseResFile( saveResFile );
  228.  
  229.     return( err );
  230. }
  231.  
  232.  
  233. static void GetFinderFilename(
  234. /* <-- */    StringPtr       _finderFilename)
  235. {
  236.     Str255          _defaultFinderFilename="¥pFinder";
  237.     StringPtr       _lowMemFinderName;
  238.  
  239.     _lowMemFinderName = LMGetFinderName();
  240.     if( (_lowMemFinderName != (StringPtr )nil) && (_lowMemFinderName[0] > 0))
  241.         BlockMove(_lowMemFinderName, _finderFilename, _lowMemFinderName[0]+1);
  242.     else
  243.         BlockMove(_defaultFinderFilename, _finderFilename, _defaultFinderFilename[0]+1);
  244. }
  245.  
  246.  
  247. /*    ------------------------------------------------------------------
  248.     GetIcon        This is an IconAction procedure to fill in one
  249.                     slot of an icon suite, given a file type, creator,
  250.                     and desktop database.
  251.     ------------------------------------------------------------------ */
  252. static    pascal OSErr GetIconProc(ResType theType, Handle *theIcon, void *yourDataPtr)
  253. {
  254.     OSErr            err;
  255.     GetIconData        *data;
  256.     DTPBRec            deskRec;
  257.  
  258.     err = noErr;
  259.     data = (GetIconData *)yourDataPtr;
  260.     *theIcon = NewHandle( kLarge8BitIconSize );
  261.  
  262.     if( !(*theIcon) )
  263.     {
  264.         err = memFullErr;
  265.     }
  266.     else
  267.     {
  268.         HLock( *theIcon );
  269.     
  270.         deskRec.ioDTRefNum        = data->DTRefNum;
  271.         deskRec.ioDTBuffer        = **theIcon;
  272.         deskRec.ioDTReqCount    = kLarge8BitIconSize;
  273.         deskRec.ioFileCreator    = data->fileCreator;
  274.         deskRec.ioFileType        = data->fileType;
  275.     
  276.         switch( theType )
  277.         {
  278.             case large1BitMask:
  279.                 deskRec.ioIconType = kLargeIcon;
  280.                 break;
  281.     
  282.             case large4BitData:
  283.                 deskRec.ioIconType = kLarge4BitIcon;
  284.                 break;
  285.     
  286.             case large8BitData:
  287.                 deskRec.ioIconType = kLarge8BitIcon;
  288.                 break;
  289.     
  290.             case small1BitMask:
  291.                 deskRec.ioIconType = kSmallIcon;
  292.                 break;
  293.     
  294.             case small4BitData:
  295.                 deskRec.ioIconType = kSmall4BitIcon;
  296.                 break;
  297.     
  298.             case small8BitData:
  299.                 deskRec.ioIconType = kSmall8BitIcon;
  300.                 break;
  301.             
  302.             default:
  303.                 // The desktop database does not have "mini" icons
  304.                 deskRec.ioIconType = 1000;
  305.                 break;
  306.         }
  307.  
  308.         err = PBDTGetIconSync( &deskRec );
  309.         if(err == noErr)
  310.         {
  311.             HUnlock( *theIcon );
  312.             SetHandleSize(*theIcon, deskRec.ioDTActCount);
  313.         }
  314.         else
  315.         {
  316.             DisposeHandle( *theIcon );
  317.             *theIcon = NULL;
  318.             err = noErr;
  319.         }
  320.     }
  321.     return( err );
  322. }
  323.  
  324.  
  325. /*    ------------------------------------------------------------------
  326.     Find_desktop_database            Find the reference number of a
  327.                                     desktop database containing icons
  328.                                     for a specified creator code.
  329.     The search begins on a specified volume, but covers all volumes.
  330.     ------------------------------------------------------------------ */
  331. static    short    FindDesktopDatabase(
  332. /* --> */    short    firstVRefNum,
  333. /* --> */    OSType    fileCreator)    // returns a DT refnum or 0
  334. {
  335. //    OSErr            err;
  336.     VolumeParam        vpb;
  337.     short            DTRefNum = 0;
  338.  
  339.     if( !InOneDesktop(firstVRefNum, fileCreator, &DTRefNum) )
  340.     {
  341.         vpb.ioNamePtr = NULL;
  342.         for(vpb.ioVolIndex = 1; PBGetVInfoSync((ParmBlkPtr )&vpb) == noErr; ++vpb.ioVolIndex)
  343.         {
  344.             if(vpb.ioVRefNum == firstVRefNum)
  345.                 continue;
  346.             if( InOneDesktop(vpb.ioVRefNum, fileCreator, &DTRefNum) )
  347.                 break;
  348.         }
  349.     }
  350.     return( DTRefNum );
  351. }
  352.  
  353.  
  354.  
  355. /*    ------------------------------------------------------------------
  356.     InOneDesktop            Determine whether the desktop database for
  357.                             one particular volume contains icons for
  358.                             a given creator code, and if so, return its
  359.                             reference number.
  360.     ------------------------------------------------------------------
  361. */
  362. static    Boolean    InOneDesktop(
  363. /* --> */    short    vRefNum,
  364. /* --> */    OSType    fileCreator,
  365. /* <-- */    short    *dtRefNum)
  366. {
  367.     OSErr        err;
  368.     DTPBRec        deskRec;
  369.     Boolean        retVal;
  370.     
  371.     HParamBlockRec         _myHPB;
  372.     GetVolParmsInfoBuffer  _infoBuffer;
  373.     
  374.     retVal = false;    // default to failure
  375.     deskRec.ioNamePtr = NULL;
  376.     deskRec.ioVRefNum = vRefNum;
  377.     
  378.     // check to make sure we've got a database first:
  379.     _myHPB.ioParam.ioNamePtr  = (StringPtr)nil;
  380.     _myHPB.ioParam.ioVRefNum  = vRefNum;
  381.     _myHPB.ioParam.ioBuffer   = (Ptr)&_infoBuffer;
  382.     _myHPB.ioParam.ioReqCount = sizeof(_infoBuffer);
  383.     if ( ((err=PBHGetVolParmsSync(&_myHPB))!=noErr) ||
  384.     ((_infoBuffer.vMAttrib&(1L<<bHasDesktopMgr))==0) )
  385.         return( retVal );
  386.  
  387.     err = PBDTGetPath( &deskRec );
  388.     if( !err )
  389.     {
  390.         /*    We want to ignore any non-icon data, such as the 'paul'
  391.             item that is used for drag-and-drop. */
  392.         deskRec.ioFileCreator = fileCreator;
  393.         deskRec.ioIndex = 1;
  394.         do
  395.         {
  396.             deskRec.ioTagInfo = 0;
  397.             err = PBDTGetIconInfoSync( &deskRec );
  398.             deskRec.ioIndex += 1;
  399.         }while( (err == noErr) && (deskRec.ioIconType <= 0) );
  400.     
  401.         if(err == noErr)
  402.         {
  403.             retVal = true;
  404.             *dtRefNum = deskRec.ioDTRefNum;
  405.         }
  406.     }
  407.     return( retVal );
  408. }
  409.  
  410.  
  411. static pascal OSErr GetResourceIcons(
  412. /* <-- */    Handle    *theSuite,
  413. /* --> */    short    theID,
  414. /* --> */    long    theSelector)
  415. {
  416.     OSErr    err;
  417.     
  418.     err = Get1IconSuite(theSuite, theID, theSelector);
  419.     if(err == noErr)
  420.     {
  421.         err = CopyEachIcon( *theSuite );
  422.     }
  423.     return( err );
  424. }
  425.  
  426.  
  427. static pascal OSErr CopyOneIcon(
  428. /* --> */    ResType        /*theType*/,
  429. /* <-> */    Handle        *theIcon,
  430. /* --- */    void        */*yourDataPtr*/)
  431. {
  432.     OSErr    err;
  433.     
  434.     if(*theIcon != NULL)
  435.     {
  436.         LoadResource( *theIcon );
  437.         err = HandToHand( theIcon );
  438.         if(err != noErr)
  439.             *theIcon = NULL;
  440.     }
  441.     return( noErr );
  442. }
  443.  
  444.  
  445. static OSErr CopyEachIcon(
  446. /* <-> */    Handle theSuite)
  447. {
  448.     IconActionUPP    copyOneIconProc;
  449.     OSErr            err;
  450.     copyOneIconProc = NewIconActionProc( CopyOneIcon );
  451.     err = ForEachIconDo(theSuite, svAllAvailableData, copyOneIconProc, NULL);
  452.     DisposeRoutineDescriptor( copyOneIconProc );
  453.     return( err );
  454. }
  455.  
  456.  
  457. typedef struct genericIconInfo { OSType type; short id; } GenericIconInfo;
  458. static GenericIconInfo gGenericFinderIcons[]={ {'ifil',12500},
  459.                                                {'ifil',12500},
  460.                                                {'sfil',14000},
  461.                                                {'ffil',14500},
  462.                                                {'tfil',14501},
  463.                                                {'kfil',14750},
  464.                                                {'FFIL',15500},
  465.                                                {'DFIL',15750}
  466.                                               };
  467. static GenericIconInfo gGenericSysIcons[]={ {kContainerFolderAliasType,genericFolderIconResource},
  468.                                             {kContainerTrashAliasType,trashIconResource},
  469.                                             {kSystemFolderAliasType,systemFolderIconResource},
  470.                                             {'INIT',genericExtensionIconResource},
  471.                                             {'APPL',genericApplicationIconResource},
  472.                                             {'dfil',genericDeskAccessoryIconResource},
  473.                                             {'pref',genericPreferencesIconResource},
  474.                                             {kAppleMenuFolderAliasType,appleMenuFolderIconResource},
  475.                                             {kControlPanelFolderAliasType,controlPanelFolderIconResource},
  476.                                             {kExtensionFolderAliasType,extensionsFolderIconResource},
  477.                                             {kPreferencesFolderAliasType,preferencesFolderIconResource},
  478.                                             {kStartupFolderAliasType,startupFolderIconResource},
  479.                                             {kApplicationAliasType,genericApplicationIconResource},
  480.                                             {kExportedFolderAliasType,ownedFolderIconResource},
  481.                                             {kDropFolderAliasType,dropFolderIconResource},
  482.                                             {kSharedFolderAliasType,sharedFolderIconResource},
  483.                                             {kMountedFolderAliasType,mountedFolderIconResource}
  484.                                            };
  485.  
  486.  
  487. static short    FindGenericIconID(
  488. /* --> */    OSType theType,
  489. /* <-- */    Boolean    *inFinder)
  490. {
  491.     
  492.    short id=genericDocumentIconResource; // default
  493.    GenericIconInfo *_icon, *_endIcon;
  494.    
  495.     for (_icon=gGenericFinderIcons,_endIcon=_icon+sizeof(gGenericFinderIcons)/sizeof(GenericIconInfo);
  496.          (_icon<_endIcon)&&(_icon->type!=theType); _icon++) ;
  497.     if (!(*inFinder=(_icon<_endIcon)))
  498.         for (_icon=gGenericSysIcons,_endIcon=_icon+sizeof(gGenericSysIcons)/sizeof(GenericIconInfo);
  499.              (_icon<_endIcon)&&(_icon->type!=theType); _icon++) ;
  500.     if (_icon<_endIcon)
  501.         id = _icon->id;
  502.  
  503.     return( id );
  504. }
  505.  
  506.  
  507. /*    --------------------------------------------------------------------
  508.     Get1IconSuite            Like GetIconSuite, but only looks in
  509.                             the current resource file.
  510.     
  511.     In case you're wondering why it would be necessary to ensure that
  512.     icons come from only one file, suppose you're looking at a
  513.     file that has its custom icon bit set, but for some reason does
  514.     not contain a custom icon, or at least not a full family.
  515.     Way down the resource chain, there may be another file, say a
  516.     font file, that does have a full family of custom icons. 
  517.     So you get an unexpected icon.
  518.     -------------------------------------------------------------------- */
  519.  
  520. static pascal OSErr Get1IconSuite(
  521. /* <-- */    Handle    *theSuite,
  522. /* --> */    short    theID,
  523. /* --> */    long    theSelector)
  524. {
  525.     OSErr        err;
  526.     IconActionUPP    get1IconProc;
  527.  
  528.     err = NewIconSuite( theSuite );
  529.     if( !err )
  530.     {
  531.         get1IconProc = NewIconActionProc( Get1Icon );
  532.         err = ForEachIconDo(*theSuite, theSelector, get1IconProc, &theID);
  533.         DisposeRoutineDescriptor( get1IconProc );
  534.     }
  535.     return( err );
  536. }
  537.  
  538.  
  539. static pascal OSErr Get1Icon(
  540. /* --> */    ResType    theType,
  541. /* <-> */    Handle    *theIcon,
  542. /* --> */    short    *resID)
  543. {
  544.     *theIcon = Get1Resource(theType, *resID);
  545.  
  546.     return( noErr );
  547. }
  548.  
  549.  
  550. static pascal OSErr TestHandle(ResType /*theType*/, Handle *theIcon, void *yourDataPtr)
  551. {
  552.     if(*theIcon != NULL)
  553.         *(Boolean *)yourDataPtr = false;    // not empty!
  554.  
  555.     return( noErr );
  556. }
  557.  
  558.  
  559. Boolean IsSuiteEmpty( Handle theSuite )
  560. {
  561.     Boolean            retVal;
  562.     IconActionUPP    testHandleProc;
  563.  
  564.     testHandleProc = NewIconActionProc( TestHandle );
  565.     
  566.     retVal = true;
  567.     ForEachIconDo(theSuite, svAllAvailableData, testHandleProc, &retVal);
  568.     DisposeRoutineDescriptor( testHandleProc );
  569.  
  570.     return( retVal );
  571. }
  572.  
  573.  
  574.